package com.hugang.newfeature.streamapi;

import com.hugang.newfeature.methodrefernce.Employee;
import com.hugang.newfeature.methodrefernce.EmployeeData;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Stream;

/**
 * StreamAPI中间操作
 *
 * @author hg
 * @date 2020/6/26 19:57
 */
public class StreamAPITest1 {

    /**
     * 1、筛选与切片
     */
    @Test
    public void test1() {
        List<Employee> employees = EmployeeData.getEmployees();
        Stream<Employee> stream = employees.stream();
        //filter(Predicate p) —— 接收Lambda，从流中排除某些元素
        //查询员工表中薪资大于7000的员工信息
        stream.filter(e -> e.getSalary() > 7000).forEach(System.out::println);
        System.out.println();

        //limit(n) —— 截断流，使其元素不超过给定数量
        employees.stream().limit(5).forEach(System.out::println);
        System.out.println();

        //skip(n) —— 跳过元素，返回一个扔掉了前n个元素的流。若流中元素不足n个，则返回一个空流，与limit(n)互补
        employees.stream().skip(30).forEach(System.out::println);
        System.out.println();

        //distinct() —— 筛选，通过流所生成元素的hashCode()和equals()去除重复元素
        employees.add(new Employee(1002, "刘强东", 23, 44.0));
        employees.add(new Employee(1002, "刘强东", 23, 44.0));
        employees.add(new Employee(1002, "刘强东", 23, 44.0));
        employees.stream().distinct().forEach(System.out::println);
    }

    /**
     * 2、映射
     */
    @Test
    public void test2() {
        //map(Function f) —— 接收一个函数作为参数，将元素转换成其他形式或提取信息，
        //该函数会被应用到每个元素上，并将其映射成一个新元素
        List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
//        list.stream().map(s -> s.toUpperCase()).forEach(System.out::println);
        list.stream().map(String::toUpperCase).forEach(System.out::println);
        System.out.println();

        //练习1：获取名字长度大于3的员工的名字
        List<Employee> employees = EmployeeData.getEmployees();
        //以下三种写法都可以，第一种不太行
        employees.stream().map(e -> e.getName().length() > 3 ? e.getName() : "").forEach(System.out::println);
        employees.stream().map(Employee::getName).filter(s -> s.length() > 3).forEach(System.out::println);
        employees.stream().filter(employee -> employee.getName().length() > 3).map(Employee::getName).forEach(System.out::println);
        System.out.println();

        //练习2：
        Stream<Stream<Character>> streamStream = list.stream().map(StreamAPITest1::fromStringToStream);
        streamStream.forEach(s -> s.forEach(System.out::println));
        System.out.println();
        //flatMap(Function f) —— 接收一个函数作为参数，将流中的每个值都换成另一个流，然后把所有流连接成一个流
        Stream<Character> characterStream = list.stream().flatMap(StreamAPITest1::fromStringToStream);
        characterStream.forEach(System.out::println);
    }

    //将字符串中的多个字符构成的集合转换为对应的Stream的实例
    public static Stream<Character> fromStringToStream(String str){
        ArrayList<Character> list = new ArrayList<>();
        for (Character c : str.toCharArray()){
            list.add(c);
        }
        return list.stream();
    }

    @Test
    public void test3(){
        ArrayList list1 = new ArrayList();
        list1.add(1);
        list1.add(2);
        list1.add(3);

        ArrayList list2 = new ArrayList();
        list2.add(4);
        list2.add(5);
        list2.add(6);

//        list1.add(list2);
        list1.addAll(list2);
        System.out.println(list1);
    }

    /**
     * 3、排序
     */
    @Test
    public void test4(){
        //sorted() —— 自然排序
        List<Integer> in = Arrays.asList(12, 22, 45, 112, 4, 5, 2, 5434, 65, 345, 435, 63, 64);
        in.stream().sorted().forEach(System.out::println);
        System.out.println();
        //抛异常，原因：Employee类没有实现Comparable接口
//        List<Employee> employees = EmployeeData.getEmployees();
//        employees.stream().sorted().forEach(System.out::println);


        //sorted(Comparator com) —— 定制排序
        List<Employee> employees = EmployeeData.getEmployees();
        //按照薪资排序
        employees.stream().sorted((o1, o2) -> Double.compare(o1.getSalary(),o2.getSalary())).forEach(System.out::println);
        //第二种写法
        employees.stream().sorted(Comparator.comparing(Employee::getSalary)).forEach(System.out::println);
        System.out.println();
        //按照年龄从小到大，薪资从大到小
        employees.stream().sorted((o1, o2) -> {
            if (o1.getAge() > o2.getAge()){
                return 1;
            } else if (o1.getAge() < o2.getAge()) {
                return -1;
            } else {
                return Double.compare(o2.getSalary(), o1.getSalary());
            }
        }).forEach(System.out::println);
    }

}
